package eworldpacs.ui;

import android.app.Activity;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import leadtools.RasterGrayscaleMode;
import leadtools.RasterImage;
import leadtools.dicom.DicomDataSet;
import leadtools.dicom.DicomElement;
import leadtools.dicom.DicomImageInformation;
import leadtools.dicom.DicomImagePhotometricInterpretationType;
import leadtools.dicom.DicomTag;
import leadtools.imageprocessing.core.ApplyLinearVoiLookupTableCommand;
import leadtools.imageprocessing.core.GetLinearVoiLookupTableCommand;
import leadtools.imageprocessing.core.VoiLookupTableCommandFlags;

public class WindowLeveler implements OnTouchListener {
   
   
   ApplyLinearVoiLookupTableCommand _voiLUTCommand;
   RasterImage _image;
   DicomDataSet _ds;
   private int _minWindowCenter;
   private int _maxWindowCenter;
   private int _minWindowWidth;
   private int _maxWindowWidth;
   private boolean _windowLevelEnabled;
   private int _windowLevelSensitivity;
   private double _windowWidth;
   private double _windowCenter;
   private double _initialWidth;
   private double _initialCenter;
   private DicomImageInformation _imageInfo;
   private float _lastX;
   private float _lastY;
   private Activity _ownerActivity;
   
   public WindowLeveler(RasterImage image, DicomDataSet ds, Activity ownerActivity){
      _voiLUTCommand = new ApplyLinearVoiLookupTableCommand();
      _ds = ds;
      _image = image;
      DicomElement pixdataElement = _ds.findFirstElement(null, DicomTag.PIXEL_DATA, true);
      _imageInfo = _ds.getImageInformation(pixdataElement, 0);
      _windowLevelEnabled = isGray(_image);
      _ownerActivity = ownerActivity;
      if (_windowLevelEnabled){
         InitWindowLevelValues();
         onWindowLevelChanged((int)_windowWidth, (int)_windowCenter);
      }
   }
   
   public boolean onTouch(final View view, final MotionEvent event) {
      switch (event.getAction())
      {
          case MotionEvent.ACTION_DOWN:
          {
            _lastX = event.getX();
            _lastY = event.getY();   
              break;
          }
          case MotionEvent.ACTION_MOVE:
          {
              float currentX = event.getX();
              float currentY = event.getY();
              float dx = currentX - _lastX;
              float dy = currentY - _lastY;
              
              _windowCenter += dx * _windowLevelSensitivity;
               _windowWidth -= dy * _windowLevelSensitivity;
               updateWindowLevel();
              Log.i("WindowCenter, WindowWidth", String.format("%.3f, %.3f", _windowCenter, _windowWidth));
              _lastX = currentX;
              _lastY = currentY;
              break;
          }
          case MotionEvent.ACTION_UP:
          {
            break;
          }
      }
        return true;
    }
   
   private void calculateMinMaxCenter()
    {

       _minWindowCenter = -65535;
       _maxWindowCenter = 65535;
    }

    private void calculateMinMaxWidth()
    {
       _minWindowWidth = 1;
       _maxWindowWidth = ((_maxWindowCenter - _minWindowCenter) * 2);
    }
    
    private void calculateSensitivyValue()
    {
       if (_image == null)
       {
          _windowLevelSensitivity = 1;
          return;
       }

       int maxVal = _image.getMaxValue();

       if (maxVal == -1)
          maxVal = (1 << _image.getBitsPerPixel()) - 1;

       int delta = maxVal - _image.getMinValue();

       _windowLevelSensitivity = Math.max(1, (delta >> 12));
    }
    
    private void InitWindowLevelValues()
    {
       if (_windowLevelEnabled)
       {
          calculateSensitivyValue();
          calculateMinMaxCenter();
          calculateMinMaxWidth();

          try
          {
             GetLinearVoiLookupTableCommand cmd = new GetLinearVoiLookupTableCommand();
             cmd.run(_image);
             _windowWidth = cmd.getWidth();
             _windowCenter = cmd.getCenter();
          }
          catch (Exception ex)
          {
             _windowWidth = (_image.getMaxValue() - _image.getMinValue());
             _windowCenter = (_image.getMaxValue() + _image.getMinValue() + 1) >> 1;
          }
          
          _initialWidth = _windowWidth;
          _initialCenter = _windowCenter;
       }
    }
    
    
    public void resetLUT()
    {
       if (_windowLevelEnabled && _image != null)
       {
          _windowWidth = _initialWidth;
          _windowCenter = _initialCenter;

          //InvalidateImage();
       }
    }
    
    private void updateWindowLevel()
    {
       if (_windowLevelEnabled)
       {
          _windowWidth = Math.max(_windowWidth, _minWindowWidth);
          _windowWidth = Math.min(_windowWidth, _maxWindowWidth);
          _windowCenter = Math.max(_windowCenter, _minWindowCenter);
          _windowCenter = Math.min(_windowCenter, _maxWindowCenter);

          _voiLUTCommand.setWidth(_windowWidth);
          _voiLUTCommand.setCenter(_windowCenter);
          if (_imageInfo.getPhotometricInterpretation() == DicomImagePhotometricInterpretationType.forValue(DicomImagePhotometricInterpretationType.MONOCHROME1.getValue()))
             _voiLUTCommand.setFlags(VoiLookupTableCommandFlags.REVERSE_ORDER.getValue() | VoiLookupTableCommandFlags.UPDATE_MIN_MAX.getValue());
          else
             _voiLUTCommand.setFlags(VoiLookupTableCommandFlags.UPDATE_MIN_MAX.getValue());

          _voiLUTCommand.run(_image);
          onWindowLevelChanged((int)_windowWidth,(int)_windowCenter);
       }
    }
    
   private boolean isGray(RasterImage image)
    {
       boolean isGray = false;
       if (image != null)
       {
          isGray = (image.getGrayscaleMode() != RasterGrayscaleMode.forValue(RasterGrayscaleMode.NONE.getValue()));
       }
       return isGray;
 
    }
   
   protected Activity getOwnerActivity(){
      return _ownerActivity; 
   }
   
   protected void setOwnerActivity(Activity ownerActivity){
      _ownerActivity = ownerActivity;
   }
   
   protected void setImage(RasterImage image){
      _image = image;
   }
   
   public void forceApplyLUT(RasterImage image)
    {
      _voiLUTCommand.run(image);
    }
   
   public boolean canWindowLevel()
   {
      return _windowLevelEnabled;
   }
   
   public void refresh(){
      updateWindowLevel();
   }

   protected void onWindowLevelChanged(int width, int center){}
   
   protected void onActivityRecreated(){};
}
